#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <time.h>

#include "public.h"

static void xy_sig_handler_green_on(int , siginfo_t *, void *);
static void xy_sig_handler_green_off(int , siginfo_t *, void *);
static void xy_sig_handler_yellow_on(int , siginfo_t *, void *);
static void xy_sig_handler_yellow_off(int , siginfo_t *, void *);
static void xy_sig_handler_red_on(int , siginfo_t *, void *);
static void xy_sig_handler_red_off(int , siginfo_t *, void *);

static void xy_sig_handler(int signo, siginfo_t * si, void * context) 
{
  ac_traces(MSG_LEVEL_INFO, "signal handler function.");

  switch(signo - SIGRTMIN) {
  case 10:
    xy_sig_handler_green_on(signo, si, context);
    break;

  case 11:
    xy_sig_handler_green_off(signo, si, context);
    break;

  case 12:
    xy_sig_handler_yellow_on(signo, si, context);
    break;

  case 13:
    xy_sig_handler_yellow_off(signo, si, context);
    break;

  case 14:
    xy_sig_handler_red_on(signo, si, context);
    break;

  case 15:
    xy_sig_handler_red_off(signo, si, context);
    break;

  case 16:
    ac_traces(MSG_LEVEL_INFO, "poweroff signal handler");
    xy_sig_handler_green_off(signo, si, context);
    xy_sig_handler_yellow_off(signo, si, context);
    xy_sig_handler_red_off(signo, si, context);
    b_quit = 1;
    break;

  default:
    ac_traces(MSG_LEVEL_INFO, "no signal number");
    break;
  }
}

static void xy_sig_handler_green_on(int signo, siginfo_t * si, void * context)
{
  xy_green_bright();
}

static void xy_sig_handler_green_off(int signo, siginfo_t * si, void * context)
{
  xy_green_extinguish();
}

static void xy_sig_handler_yellow_on(int signo, siginfo_t * si, void * context)
{
  xy_yellow_bright();
}

static void xy_sig_handler_yellow_off(int signo, siginfo_t * si, void * context)
{
  xy_yellow_extinguish();
}

static void xy_sig_handler_red_on(int signo, siginfo_t * si, void * context)
{
  xy_red_bright();
}

static void xy_sig_handler_red_off(int signo, siginfo_t * si, void * context)
{
  xy_red_extinguish();
}

void xy_sig_manager_init(void)
{
  struct sigaction act;
  sigset_t mask;

  ac_traces(MSG_LEVEL_INFO, "signal manager init");

  sigemptyset(&mask);
  act.sa_sigaction = xy_sig_handler;
  act.sa_mask = mask;
  act.sa_flags = SA_SIGINFO;

  sigaction(SIG_GREEN_ON, &act, NULL);
  sigaction(SIG_GREEN_OFF, &act, NULL);
  sigaction(SIG_YELLOW_ON, &act, NULL);
  sigaction(SIG_YELLOW_OFF, &act, NULL);
  sigaction(SIG_RED_ON, &act, NULL);
  sigaction(SIG_RED_OFF, &act, NULL);
  sigaction(SIG_POWER_OFF, &act, NULL);
}

void xy_sig_sendsig(int sig, int value)
{
  union sigval val;
  int pid;

  val.sival_int = value;
  ac_traces(MSG_LEVEL_INFO, "signal is %d, value is 0x%x\n", sig, value);
  pid = getpid();
  sigqueue(pid, sig, val);
}
